package com.example.mytestdemo.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Region
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.SoundPool
import android.os.Process
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import com.example.mytestdemo.R


class FunctionConstraintLayout : FrameLayout {

    constructor(context: Context) : super(context)
    constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet)
    constructor(context: Context, attributeSet: AttributeSet?, style: Int = 0) : super(
        context,
        attributeSet,
        style
    )

    companion object {

        private val sSoundPool: SoundPool by lazy {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                val audioAttributes = AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA).build()
                SoundPool.Builder().setMaxStreams(100).setAudioAttributes(audioAttributes).build()
            } else {
                SoundPool(100, AudioManager.STREAM_MUSIC, 1)
            }
        }

        private val sPaint = Paint().apply {
            this.color = Color.RED
            this.textSize = 20.0f
            this.isAntiAlias = true
        }

        private const val TAG = "FunctionConstraintLayou"

        private const val ANCHOR_WIDTH_PERCENT = 10

        private const val CHECK_INTERNAL = 5 * 1000
    }

    private var _onTouchTimeStamp = System.currentTimeMillis()

    private val _soundId = sSoundPool.load(context, R.raw.click, 1)

    private val _anchorSize by lazy {
        if (width > height) height / ANCHOR_WIDTH_PERCENT else width / ANCHOR_WIDTH_PERCENT
    }

    private val _leftTopRegion by lazy {
        Region(0, 0, _anchorSize, _anchorSize)
    }

    private val _rightTopRegion by lazy {
        Region((width - _anchorSize), 0, width, _anchorSize)
    }

    private val _rightBottomRegion by lazy {
        Region((width - _anchorSize), (height - _anchorSize), width, height)
    }

    private val _leftBottomRegion by lazy {
        Region(0, (height - _anchorSize), _anchorSize, height)
    }

    private val _rigthCenterRegion by lazy {
        Region((width - _anchorSize), (height - _anchorSize) / 2, width, (height + _anchorSize) / 2)
    }


    private val _dispatchRecordList = mutableListOf<DispatchRecord>()

    private var _gestureMode = false

    private val _anchorList = mutableListOf<Anchor>()

    var downX: Int = 0
    var downY: Int = 0
    var upX: Int = 0
    var upY: Int = 0

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        ev?.run {
            if (!_gestureMode) {
                val record =
                    buildDispatchRecord(ev.x.toInt(), ev.y.toInt(), ev.x.toInt(), ev.y.toInt())
                record?.also {
                    _dispatchRecordList.add(it)
                }
                _gestureMode = checkGestureMode()
                if (_gestureMode) {
                    postInvalidate()
                    postDelayed(Runnable {
                        synchronized(TAG) {
                            _gestureMode = false
                            _dispatchRecordList.clear()
                            postInvalidate()
                        }
                    }, CHECK_INTERNAL * 2L)
                }
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        if (_gestureMode) {
            return true
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        if (_gestureMode) {
            // 间隔5s，开启第二次检测
            if (System.currentTimeMillis() - _onTouchTimeStamp >= CHECK_INTERNAL) {
                _anchorList.clear()
            }
            when (ev?.action) {

                MotionEvent.ACTION_DOWN -> {
                    downX = ev.x.toInt()
                    downY = ev.y.toInt()
                }

                MotionEvent.ACTION_UP -> {
                    upX = ev.x.toInt()
                    upY = ev.y.toInt()

                    val anchor = buildAnchor(downX, downY, upX, upY)
                    anchor?.run {
                        _anchorList.add(anchor)
                        sSoundPool.play(_soundId, 0.1f, 0.1f, 1, 0, 1f)
                    }
                    if (checkTouchGesture()) {
                        Log.e(TAG, "GESTURE IS OK")
                        Process.killProcess(Process.myPid())
                    } else {
                        Log.e(TAG, "anchor is ${_anchorList.toString()}")
                    }
                }
            }
            _onTouchTimeStamp = System.currentTimeMillis()
        }
        return _gestureMode
    }


    override fun drawChild(canvas: Canvas?, child: View?, drawingTime: Long): Boolean {
        val result = super.drawChild(canvas, child, drawingTime)
        canvas?.run {
            save()
            if (_gestureMode) {
                canvas.rotate(90f, (width - _anchorSize / 2).toFloat(), height / 2.0f)
                drawText("开启手势识别", (width - _anchorSize).toFloat(), height / 2.0f, sPaint)
            }
            restore()
        }
        return result
    }


    private fun buildAnchor(startX: Int, startY: Int, endX: Int, endY: Int): Anchor? {

        if (_leftTopRegion.contains(startX, startY) && _leftTopRegion.contains(endX, endY)) {
            return Anchor.LEFT_TOP
        } else if (_rightTopRegion.contains(startX, startY) && _rightTopRegion.contains(
                endX,
                endY
            )
        ) {
            return Anchor.RIGHT_TOP
        } else if (_rightBottomRegion.contains(startX, startY) && _rightBottomRegion.contains(
                endX,
                endY
            )
        ) {
            return Anchor.RIGHT_BOTTOM
        } else if (_leftBottomRegion.contains(startX, startY) && _leftBottomRegion.contains(
                endX,
                endY
            )
        ) {
            return Anchor.LEFT_BOTTOM
        } else if ((endX - startX) >= width * 0.6) {
            return Anchor.LEFT_RIGHT
        }
        return null
    }


    private fun buildDispatchRecord(
        startX: Int,
        startY: Int,
        endX: Int,
        endY: Int
    ): DispatchRecord? {
        return if (_rigthCenterRegion.contains(startX, startY) && _rigthCenterRegion.contains(
                endX,
                endY
            )
        ) DispatchRecord(System.currentTimeMillis()) else null
    }

    private fun checkGestureMode(): Boolean {
        synchronized(TAG) {
            val sizeOk = _dispatchRecordList.size >= 5
            return sizeOk && (_dispatchRecordList[_dispatchRecordList.size - 1].timeStamp - _dispatchRecordList[_dispatchRecordList.size - 5].timeStamp <= CHECK_INTERNAL)
        }
    }


    private fun checkTouchGesture(): Boolean {
        val size = _anchorList.size
        if (size >= 5) {
            return (_anchorList[size - 1] == Anchor.LEFT_RIGHT) && (_anchorList[size - 2] == Anchor.LEFT_BOTTOM)
                    && (_anchorList[size - 3] == Anchor.RIGHT_BOTTOM) && (_anchorList[size - 4] == Anchor.RIGHT_TOP)
                    && (_anchorList[size - 5] == Anchor.LEFT_TOP)
        }
        return false
    }


    private enum class Anchor(val index: Int) {
        LEFT_TOP(0), RIGHT_TOP(1),
        RIGHT_BOTTOM(2), LEFT_BOTTOM(3),
        LEFT_RIGHT(4)
    }

    private class DispatchRecord(val timeStamp: Long)
}